package nettyexample.command;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import lombok.Data;
import nettyexample.entity.LoginRequestPacket;
import nettyexample.entity.LoginResponsetPacket;
import nettyexample.sericalizer.JSONSerializer;
import nettyexample.sericalizer.Serializer;

import java.util.HashMap;
import java.util.Map;

import static nettyexample.command.Command.LOGIN_REQUEST;
import static nettyexample.command.Command.LOGIN_RESPONSE;


/**
 * @author zoush
 * @time 2024/12/18 11:25
 */
@Data
public class PacketCodeC extends JSONSerializer {

    //魔数
    private static final int MAGIC_NUMBER = 0x12345678;

    //创建一个静态方法共外部调用
    public static final PacketCodeC INSTANCE = new PacketCodeC();

    //创建两个数组用来存储序列化和反序列化对象
    private final Map<Byte, Class<? extends Packet>> packetTypeMap;
    private final Map<Byte, Serializer> serializerMap;

    public PacketCodeC() {
        packetTypeMap = new HashMap<>();
        packetTypeMap.put(LOGIN_REQUEST, LoginRequestPacket.class);
        packetTypeMap.put(LOGIN_RESPONSE, LoginResponsetPacket.class);
        serializerMap = new HashMap<>();
        Serializer serializer = new JSONSerializer();
        serializerMap.put(serializer.getSerializerAlogrithm(), serializer);
    }

    /**
     * 编码
     * 魔数 + 版本号 + 算法 + 指令类型 + 数据长度 + 数据
     *
     * @param bufAllocator
     * @param packet
     * @return
     */
    public ByteBuf encode(ByteBufAllocator bufAllocator, Packet packet) {
        ByteBuf byteBuf = bufAllocator.ioBuffer();
        // 2. 序列化 Java 对象
        byte[] serialize = Serializer.DEFAULT.serialize(packet);

        byteBuf.writeByte(MAGIC_NUMBER);

        byteBuf.writeByte(packet.getVersion());

        byteBuf.writeByte(Serializer.DEFAULT.getSerializerAlogrithm());

        byteBuf.writeByte(packet.getCommand());

        byteBuf.writeInt(serialize.length);
        byteBuf.writeBytes(serialize);
        return byteBuf;
    }

    /**
     * 解码
     *
     * @param byteBuf
     * @return
     */
    public Packet decode(ByteBuf byteBuf) {
        // 跳过魔数
        byteBuf.skipBytes(4);
        // 跳过版本号
        byteBuf.skipBytes(1);
        //算法
        byte serializeAlgorithm = byteBuf.readByte();
        //指令
        byte command = byteBuf.readByte();
        //数据长度
        int length = byteBuf.readInt();
        byte[] bytes = new byte[length];
        byteBuf.readBytes(bytes);

        Class<? extends Packet> requestType = getRequestType(command);
        Serializer serializer = getSerializer(serializeAlgorithm);

        if (requestType != null && serializer != null) {
            return serializer.deserialize(requestType, bytes);
        } else {
            return null;
        }

    }

    private Class<? extends Packet> getRequestType(byte command) {
        return packetTypeMap.get(command);
    }

    private Serializer getSerializer(byte serializeAlgorithm) {
        return serializerMap.get(serializeAlgorithm);
    }
}
